package com.grad.webstudy.utils;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import com.grad.webstudy.constants.LinuxConstants;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.util.StringUtils;

import java.io.*;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 连接Linux
 * @Author: zjf
 * @Date: 2020/2/14 11:27.
 */
public class LinuxUtils {

    //    private static final Logger log = LoggerFactory.getLogger(RemoteCommandUtil.class);
    private static String DEFAULTCHART = "UTF-8";

    /**
     * 登录主机
     *
     * @return 登录成功返回true，否则返回false
     */
    public static Connection login(String ip,
                                   String userName,
                                   String userPwd) {

        boolean flg = false;
        Connection conn = null;
        try {
            conn = new Connection(ip);
            conn.connect();//连接
            flg = conn.authenticateWithPassword(userName, userPwd);//认证
            if (flg) {
//                log.info("=========登录成功========="+conn);
                return conn;
            }
        } catch (IOException e) {
//            log.error("=========登录失败========="+e.getMessage());
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 远程执行shll脚本或者命令
     *
     * @param cmd 即将执行的命令
     * @return 命令执行完后返回的结果值
     */
    public static String execute(Connection conn, String cmd) {
        String result = "";
        try {
            if (conn != null) {
                Session session = conn.openSession();//打开一个会话
                session.execCommand(cmd);//执行命令
                result = processStdout(session.getStdout(), DEFAULTCHART);
                //如果为得到标准输出为空，说明脚本执行出错了


                if (StringUtils.isEmpty(result)) {
                    System.out.println(("得到标准输出为空,链接conn:" + conn + ",执行的命令：" + cmd));
//                    result = processStdout(session.getStderr(), DEFAULTCHART);
                } else {
//                    log.info("执行命令成功,链接conn:"+conn+",执行的命令："+cmd);
                }
                conn.close();
                session.close();

            }
        } catch (IOException e) {
            System.out.println(("执行命令失败,链接conn:" + conn + ",执行的命令：" + cmd + "  " + e.getMessage()));
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 解析脚本执行返回的结果集
     *
     * @param in      输入流对象
     * @param charset 编码
     * @return 以纯文本的格式返回
     */
    private static String processStdout(InputStream in, String charset) {
        InputStream stdout = new StreamGobbler(in);
        StringBuffer buffer = new StringBuffer();
        ;
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));
            String line = null;
            while ((line = br.readLine()) != null) {
                buffer.append(line + "\n");
            }
        } catch (UnsupportedEncodingException e) {
//            log.error("解析脚本出错："+e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
//            log.error("解析脚本出错："+e.getMessage());
            e.printStackTrace();
        }
        return buffer.toString();
    }

    public static class FtpUtils {


        // ftp服务器地址
        public String hostname = LinuxConstants.IP;

        // ftp服务器端口号默认为21
        public Integer port = 21;

        // ftp登录账号
        public String username = LinuxConstants.USERNAME;

        // ftp登录密码fileName
        public String password = LinuxConstants.PASSWORD;

        public static FTPClient ftpClient = null;

        /**
         * 连接FTP服务器
         * 默认连接成功
         */
        public static boolean loginFtp() {
            boolean loginResult = true;
            ftpClient = new FTPClient();
            ftpClient.setControlEncoding(DEFAULTCHART);
            try {

                // 连接登录FTP服务器
                ftpClient.connect(LinuxConstants.IP, LinuxConstants.FTP_PORT);
                loginResult = ftpClient.login(LinuxConstants.USERNAME, LinuxConstants.PASSWORD);
                if (!loginResult) {
                    return loginResult;
                }

            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return loginResult;
        }

        /**
         * 上传文件
         *
         * @param pathname       ftp服务保存地址
         * @param fileName       上传到ftp的文件名
         * @param originfilename 待上传文件的名称（绝对地址）
         * @return 成功与否
         */
        public static boolean uploadFile(String pathname, String fileName, String originfilename) {
            boolean flag = false;
            InputStream inputStream = null;
            try {
                loginFtp();

                System.out.println("开始上传文件");
                inputStream = new FileInputStream(new File(originfilename));

                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
                mkdir(pathname);
                ftpClient.makeDirectory(pathname);
                ftpClient.changeWorkingDirectory(pathname);
                ftpClient.storeFile(fileName, inputStream);
                inputStream.close();
                ftpClient.logout();
                flag = true;
                System.out.println("上传文件成功");
            } catch (Exception e) {
                System.out.println("上传文件失败");
                e.printStackTrace();
            } finally {
                if (ftpClient.isConnected()) {
                    try {
                        ftpClient.disconnect();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != inputStream) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return flag;
        }

        /**
         * 上传文件
         *
         * @param pathname    ftp服务保存地址
         * @param fileName    上传到ftp的文件名
         * @param inputStream 输入文件流
         * @return
         */
        public static boolean uploadFile(String pathname, String fileName,
                                         InputStream inputStream) {
            boolean flag = false;
            try {
                System.out.println("开始上传文件");
                loginFtp();
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
                mkdir(pathname);
                ftpClient.makeDirectory(pathname);
                ftpClient.changeWorkingDirectory(pathname);
                ftpClient.storeFile(fileName, inputStream);
                inputStream.close();
                ftpClient.logout();
                flag = true;
                System.out.println("上传文件成功");
            } catch (Exception e) {
                System.out.println("上传文件失败");
                e.printStackTrace();
            } finally {
                if (ftpClient.isConnected()) {
                    try {
                        ftpClient.disconnect();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != inputStream) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return flag;
        }

        /**
         * 改变工作路径
         *
         * @param directory 工作路径
         * @return
         */
        public static boolean changeWorkingDirectory(String directory) {
            boolean flag = true;
            try {
                flag = ftpClient.changeWorkingDirectory(directory);
                if (flag) {
                    System.out.println("进入文件夹" + directory + " 成功！");

                } else {
                    System.out.println("进入文件夹" + directory + " 失败！开始创建文件夹");
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
            return flag;
        }

        /**
         * 创建目录
         * 如果FTP服务器已存在该目录，则不创建；否则，创建该目录
         *
         * @param remoteDir 远程目录
         * @return 成功与否
         * @throws IOException
         */
        public static boolean mkdir(String remoteDir) throws IOException {
            boolean success = true;
            String directory = remoteDir + "/";

            // 如果远程目录不存在，则递归创建远程服务器目录
            if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(new String(directory))) {
                int start = 0;
                int end = 0;
                if (directory.startsWith("/")) {
                    start = 1;
                } else {
                    start = 0;
                }
                end = directory.indexOf("/", start);
                String path = "";
                String paths = "";
                while (true) {
                    String subDirectory =
                            new String(remoteDir.substring(start, end).getBytes("GBK"), "ISO-8859-1");
                    path = path + "/" + subDirectory;
                    if (!existFile(path)) {
                        if (makeDirectory(subDirectory)) {
                            changeWorkingDirectory(subDirectory);
                        } else {
                            System.out.println("创建目录[" + subDirectory + "]失败");
                            changeWorkingDirectory(subDirectory);
                        }
                    } else {
                        changeWorkingDirectory(subDirectory);
                    }

                    paths = paths + "/" + subDirectory;
                    start = end + 1;
                    end = directory.indexOf("/", start);
                    // 检查所有目录是否创建完毕
                    if (end <= start) {
                        break;
                    }
                }
            }
            return success;
        }

        /**
         * 判断ftp服务器文件是否存在
         *
         * @param path
         * @return
         * @throws IOException
         */
        public static boolean existFile(String path) throws IOException {
            loginFtp();
            boolean flag = false;
            FTPFile[] ftpFileArr = ftpClient.listFiles(path);
            if (ftpFileArr.length > 0) {
                flag = true;
            }
            return flag;
        }

        /**
         * 创建文件目录
         *
         * @param dir 待创建目录
         * @return 成功与否
         */
        public static boolean makeDirectory(String dir) {
            boolean flag = true;
            try {
                flag = ftpClient.makeDirectory(dir);
                if (flag) {
                    System.out.println("创建文件夹" + dir + " 成功！");

                } else {
                    System.out.println("创建文件夹" + dir + " 失败！");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return flag;
        }

        /**
         * 下载文件
         *
         * @param pathname  FTP服务器文件目录
         * @param filename  文件名称
         * @param localpath 下载后的文件路径
         * @return
         */
        public static boolean downloadFile(String pathname, String filename, String localpath) {
            boolean flag = false;
            boolean fileExist = false;
            OutputStream os = null;
            try {
                // 连接FTP服务
                loginFtp();

                System.out.println("开始下载文件");

                // 默认FTP登录到FTP根目录下，切换目录到待下载文件目录
                ftpClient.changeWorkingDirectory(pathname);
                FTPFile[] ftpFiles = ftpClient.listFiles();
                for (FTPFile file : ftpFiles) {

                    // 查找待下载文件
                    if (filename.equalsIgnoreCase(file.getName())) {
                        fileExist = true;
                        File localFile = new File(localpath + "/" + file.getName());
                        os = new FileOutputStream(localFile);

                        // 从远程服务将文件写回到本地流
                        ftpClient.retrieveFile(file.getName(), os);
                        os.close();
                    }
                }
                ftpClient.logout();

                if (fileExist) {
                    flag = true;
                    System.out.println("下载文件成功");
                } else {
                    System.out.println("下载目录未找到该文件，文件名" + pathname + "/" + filename);
                }

            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (ftpClient.isConnected()) {
                    try {
                        ftpClient.disconnect();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (null != os) {
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return flag;
        }

        /**
         * 删除文件
         *
         * @param pathname FTP服务器保存目录
         * @param filename 要删除的文件名称
         * @return 成功与否
         */
        public static boolean deleteFile(String pathname, String filename) {
            boolean flag = false;
            try {

                loginFtp();

                System.out.println("开始删除文件");

                // 切换FTP目录
                ftpClient.changeWorkingDirectory(pathname);
                ftpClient.dele(filename);
                ftpClient.logout();
                flag = true;
                System.out.println("删除文件成功");
            } catch (Exception e) {
                System.out.println("删除文件失败");
                e.printStackTrace();
            } finally {
                if (ftpClient.isConnected()) {
                    try {
                        ftpClient.disconnect();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return flag;
        }

//            public static void main(String[] args) {
//                FtpUtils ftp = new FtpUtils();
//
////		ftp.uploadFile("upload/data", "03_Eureka01.pptx", "D://03 运行第一个Eureka程序.pptx");
////		ftp.downloadFile("upload/data", "03_Eureka01.pptx", "D://");
//                ftp.deleteFile("upload/data", "03_Eureka01.pptx");
//            }

    }


    public static List<String> executeComm(String comm) {

        List<String> strList = new ArrayList<String>();
        Process process = null;
        BufferedReader in = null;
        try {
            //整个命令作为sh的参数进行执行，以便执行重定向和管道命令，否则管道命令会被当成参数执行，得到错误结果
            String[] arr = new String[]{"/bin/sh", "-c", comm};
            process = Runtime.getRuntime().exec(arr); // 执行添加权限的命令
            process.waitFor(); // 如果执行多个命令,必须加上

            in = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String str = null;
            while ((str = in.readLine()) != null) {
                strList.add(str);
            }
        } catch (IOException e) {
//            logger.error("执行 Shell 时，出现IO异常，设置失败",e);
        } catch (InterruptedException e) {
//            logger.error("设置 IP 时，出现InterruptedException异常，设置失败",e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
//                    logger.error("关闭输入流失败",e);
                }
            }
            if (process != null) {
                process.destroy();
            }
        }
        return strList;
    }

    public static void main(String[] args) {
        Connection connection = LinuxUtils.login(LinuxConstants.IP
                , LinuxConstants.USERNAME, LinuxConstants.PASSWORD);


        System.out.println("----cd 命令----start");
        String result = LinuxUtils.execute(connection, "cd /home/docker/java-docker-app/; pwd");
        System.out.println(
                result
        );
        System.out.println("----cd 命令----end");

//        System.out.println(execute(connection, "docker run java-app-test"));
    }
}

